#ifndef __M_ROUTE_H__
#define __M_ROUTE_H__
#include <iostream>
#include "../mqCommon/mq_msg.pb.h"
#include "../mqCommon/helper.hpp"

namespace yqx
{
    class Router
    {
    public:
        /*
            routing_key只需要判断没有包含非法字符即可，注意routing_key是不能包含通配符的（* #）
        */
        static bool isLegalRoutingKey(const std::string &routing_key)
        {
            for (auto &ch : routing_key)
            {
                if ((ch >= 'a' && ch <= 'z') ||
                    (ch >= 'A' && ch <= 'Z') ||
                    (ch >= '0' && ch <= '9') ||
                    (ch == '_' || ch == '.'))
                {
                    continue;
                }
                return false;
            }
            return true;
        }
        /*
            binding_key的判断：
            1.不能包含非法字符，只能由大小写字母，数字，下划线，点，通配符组成
            2.*和#只能单独出现
            3.*和#不能连续出现
        */
        static bool isLegalBindingKey(const std::string &binding_key)
        {
            for (auto &ch : binding_key)
            {
                if ((ch >= 'a' && ch <= 'z') ||
                    (ch >= 'A' && ch <= 'Z') ||
                    (ch >= '0' && ch <= '9') ||
                    (ch == '_' || ch == '.') ||
                    (ch == '*' || ch == '#'))
                {
                    continue;
                }
                return false;
            }
            std::vector<std::string> words;
            StrHelper::split(binding_key, ".", words);
            for (int i = 0; i < words.size(); i++)
            {
                if (words[i].size() > 1 &&
                    ((words[i].find("#") != std::string::npos) ||
                     (words[i].find("*") != std::string::npos)))
                    return false;
                if (i == 0)
                    continue;
                if (words[i] == "#" && words[i - 1] == "#")
                    return false;
                if (words[i] == "#" && words[i - 1] == "*")
                    return false;
                if (words[i] == "*" && words[i - 1] == "#")
                    return false;
            }
            return true;
        }
        static bool route(ExchangeType type, const std::string &routing_key, const std::string &binding_key)
        {
            if(type == ExchangeType::DIRECT){
                return routing_key == binding_key;
            }
            else if(type == ExchangeType::FANOUT){
                return true;
            }
            return topic(routing_key, binding_key);
        }
    private:
        static bool topic(const std::string &routing_key, const std::string &binding_key){
            std::vector<std::string> rwords;
            std::vector<std::string> bwords;
            int rn = StrHelper::split(routing_key, ".", rwords);
            int bn = StrHelper::split(binding_key, ".", bwords);
            std::vector<std::vector<bool>> dp(bn + 1, std::vector<bool>(rn + 1, false));
            dp[0][0] = true;
            if(bwords[0] == "#")
                dp[1][0] = true;
            for(int i = 1; i < bn + 1; i++){
                for(int j = 1; j < rn + 1; j++){
                    if((bwords[i - 1] == "*") || (bwords[i - 1] == rwords[j - 1])){
                        dp[i][j] = dp[i - 1][j - 1];
                    }else if(bwords[i - 1] == "#"){
                        dp[i][j] = dp[i - 1][j - 1] | dp[i - 1][j]| dp[i][j - 1];
                    }
                }
            }
            return dp[bn][rn];
        }
    };
}
#endif